using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Nextensions.Text
{
	public class FileSize
	{
		private static Regex _fileSizeRe = new Regex(@"^(\d+)(G|M|K)*B$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

		private const long Giga = 1000000000;
		private const long Mega = 1000000;
		private const long Kilo = 1000;

		private static Match _match;
		private static FileSizeComparer	_comparer;

		private enum SizeUnits
		{
			b,
			KB,
			MB,
			GB
		}

		public static string FormatFileSize(double Size)
		{
			SizeUnits unit = SizeUnits.b;

			if(Size > Giga)
			{
				unit = SizeUnits.GB;
				Size /= Giga;
			}
			else if(Size > Mega)
			{
				unit = SizeUnits.MB;
				Size /= Mega;
			}
			else if(Size > Kilo)
			{
				unit = SizeUnits.KB;
				Size /= Kilo;
			}

			return string.Format("{0}{1}", ((long) Size), unit);
		}

		public static long ConvertToByteSize(string FileSize)
		{
			_match = _fileSizeRe.Match(FileSize);

			long number = long.Parse(_match.Groups[1].Value);
			long factor;

			if(string.Compare(_match.Groups[2].Value, "G", true) == 0)
				factor = 1000000000;
			else if(string.Compare(_match.Groups[2].Value, "M", true) == 0)
				factor = 1000000;
			else if(string.Compare(_match.Groups[2].Value, "K", true) == 0)
				factor = 1000;
			else
				factor = 1;

			number *= factor;

			return number;
		}

		public static bool IsValid(string FileSize)
		{
			return _fileSizeRe.IsMatch(FileSize);
		}

		public static string FileSizeFormat
		{
			get
			{
				return _fileSizeRe.ToString();
			}
		}

		public static int Compare(string Size1, string Size2)
		{
			if(_comparer == null)
				_comparer = new FileSizeComparer();
			return _comparer.Compare(Size1, Size2);
		}

		public class FileSizeComparer : IComparer<string>
		{
			public int Compare(string x, string y)
			{
				if(!IsValid(x) || !IsValid(y))
					throw new ArgumentException("One of the items being compared does not comply with the supported file size format: " + FileSizeFormat);

				return ConvertToByteSize(x).CompareTo(ConvertToByteSize(y));
			}
		}
	}
}